<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
            left: 10px;
        }
    </style>
</head>

<body>

    <div></div>
    <script>
        function interval(callback, delay = 100) {
            let id = setInterval(() => callback(id), delay)
        }
        let div = document.querySelector('div')
        interval((timeId) => {

            let left = parseInt(window.getComputedStyle(div).left)
            div.style.left = left + 10 + 'px'
            if (left >= 500) {
                clearInterval(timeId)
                interval((timeId) => {
                    let width = parseInt(window.getComputedStyle(div).width)
                    div.style.width = width - 10 + 'px'
                    if (width <= 30) {
                        clearInterval(timeId)
                    }
                })
            }
        }, 50)

        for(let i=0;i<2000000;i++){ //这里主线程 循环执行时间很长，定时器会等待主线程执行完毕 之后再执行定时器
            console.log(i)
        }


        //关于定时器 不准确的解释
        //我们常说“JavaScript 定时器不准确”，这并不是说 setTimeout 或 setInterval 本身有 bug，
        // 而是由 JavaScript 的单线程机制和**事件循环（Event Loop）**决定的。下面我们来详细解释为什么定时器的时间是“不准”的。
        //         JavaScript 是单线程的，所有代码都在一个主线程上执行。整个执行流程依赖于：

        // 调用栈（Call Stack）：当前正在执行的函数。
        // 任务队列（Callback Queue / Task Queue）：存放等待执行的回调函数（比如定时器、I/O 等）。
        // 事件循环（Event Loop）：不断检查调用栈是否为空，如果为空，就从任务队列中取出一个任务推入调用栈执行。
        // 三、一个例子说明“不准”
        // javascript
     
        // console.log('开始');

        // setTimeout(() => {
        //     console.log('定时器执行');
        // }, 1000);

        // // 模拟一段耗时很长的同步代码
        // for (let i = 0; i < 1e9; i++) {
        //     // 做一些计算
        // }

        // console.log('同步代码结束');
        // 执行顺序是：

        // 打印 '开始'
        // 设置定时器（定时器开始计时）
        // 执行长达几秒的 for 循环（阻塞主线程）
        // 打印 '同步代码结束'
        // 此时主线程空闲，事件循环检查任务队列
        // 发现定时器回调已到期，将其推入调用栈
        // 执行 console.log('定时器执行')
        // 结果：

        // 虽然设置了 1000ms，但实际执行时间可能是 3 秒甚至更久。
        // 定时器“不准”了。
    </script>
</body>

</html>